using System;
using System.Collections.Generic;
namespace NU.Analisis
{
	public class Postfijo
	{
		private static List<Object> postfijo = new List<object>();

		private Postfijo ()
		{
		}

		public static List<Object> Convertir(List<Object> infijo)
		{
			Stack<Object> pila = new Stack<object> ();
			pila.Push (Separacion.Operador.ParentesisIzquierdo);
			infijo.Add (Separacion.Operador.ParentesisDerecho);
			int i = 0;
			object actual;
			while (pila.Count > 0 && i < infijo.Count) {
				actual = infijo [i];
				if (EsNumero (actual)) {
					postfijo.Add (actual);
				}else
				if(Separacion.Operador.ParentesisIzquierdo.Equals(actual)){
					pila.Push (actual);
				}else
				if (Separacion.Operador.ParentesisDerecho.Equals (actual)) {
					while (!pila.Peek().Equals(Separacion.Operador.ParentesisIzquierdo)) {
						postfijo.Add (pila.Pop ());
					}
					pila.Pop ();
				}else
				if (EsOperador (actual)) {
					while (!pila.Peek().Equals(Separacion.Operador.ParentesisIzquierdo) && precedencia(actual, pila.Peek()) > -1) {
						postfijo.Add (pila.Pop ());
					}
					pila.Push (actual);
				}
				i++;
			}

			return postfijo;
		}

		private static bool EsOperador(object o)
		{
			return o is Separacion.Operador;
		}

		private static bool EsIdentificador(object o)
		{
			return o is string;
		}

		private static bool EsNumero(object o){
			try{
				double.Parse(o.ToString());
				return true;
			} catch (Exception){
				return false;
			}

		}

		private static int nivelOperador(Object c)
		{
			var o = (Separacion.Operador)c;
			switch (o) {
				case NU.Separacion.Operador.Modulo:
				case NU.Separacion.Operador.Division:
				case NU.Separacion.Operador.Multiplicacion:
					return 2;
				case NU.Separacion.Operador.Suma:
				case NU.Separacion.Operador.Resta:
					return 1;
				default:
					return 0;

			}

			//if("^".Equals(c))
			//	return 3;
			//else if("*/%".Contains(c.ToString()))
			//	return 2;
			//else if("+-".Contains(c.ToString()))
			//	return 1;
			//else
			//	return 0;
			
		}

		private static int precedencia(Object operador1, Object operador2)
		{
			if(nivelOperador(operador1) > nivelOperador(operador2))
				return 1;
			else if(nivelOperador(operador1) < nivelOperador(operador2))
				return -1;
			else	
				return 0;
		}
	}
}

